home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / fsstat / fsstats.awk < prev    next >
Encoding:
AWK Script  |  1988-12-06  |  16.9 KB  |  554 lines

  1. # This file combines the output from one or more invocations of fsstat
  2. # and writes the relevant data to standard out.  So far, the only data
  3. # combined are the counts of cache & disk I/O by file type, and the
  4. # deletion counts by file type.  To be added: overall I/O, and
  5. # histogram information (deletion distribution function).
  6.  
  7. # Note: some of the counts tend to overflow awk's ideas of integers.
  8. # Since awk keeps numbers internally as floating-point, we can print
  9. # them as such, but then the accuracy diminishes somewhat.  However,
  10. # the margin of error should be small.
  11.  
  12. # Initialization.  Define a few constants.  Arrays could be
  13. # initialized to 0, but awk does that for us automatically.  In some
  14. # places it would be nicer to use string subscripts, but awk used to die
  15. # with a Mem_Alloc error when I tried.  In addition, by using integers,
  16. # we can use for statements to iterate through them.
  17.  
  18. BEGIN { TEMP = 0; SWAP = 1; OBJ = 2; BINARY = 3; OTHER = 4; TOTAL = 5; 
  19.     WT_TOTAL = 1; WT_DATA = 2; WT_INDEX = 3; WT_DESC = 4; WT_DIR = 5; 
  20.     WT_VM = 6;
  21.         strings[TEMP] = "temp"; strings[SWAP] = "swap"; strings[OBJ] = "obj";
  22.     strings[BINARY] = "bin"
  23.         strings[OTHER] = "other"; state = 0; maxRow = -1; row = -1;
  24.         lastHost = ""; longestUptime = 0;
  25.     numHosts = 0; numFiles = 0;
  26. }
  27.  
  28. # The general methodology for determining what data we're looking at
  29. # is to look for a well-known string and set a state variable.
  30. # Since the inputs are effectively concatenated, each time we hit the
  31. # first line of an fsstat output, we reset the state to 0 and
  32. # initialize the "row" variable.  The states are as follows:
  33. #    state        meaning
  34. #    0        waiting to get to the interesting statistics
  35. #    1        gathering file type I/O statistics
  36. #    2        gathering overall deletion statistics
  37. #    3        gathering deletion histogram statistics
  38.  
  39. /^Fs Stats:/{state = 0; if (row > maxRow) maxRow = row; row = -1; numFiles++}
  40.  
  41. # Parse the uptime information, in the form:
  42. #        mint.Berkeley.EDU*   up   1+08:35   ...
  43. /^ +[a-z]*\.Berkeley\.EDU[ \*] *(up|down)/ {
  44.     n = split($1, spl, "*")
  45.     thisHost = spl[1]
  46.     if (thisHost != lastHost) {
  47.     lastHost = thisHost
  48.         numHosts ++
  49.     }
  50.     thisUp = $3
  51.     n = split(thisUp, spl, "+")
  52.     if (n == 1) {
  53.     days = 0
  54.     } else {
  55.     days = spl[1]
  56.     thisUp = spl[2]
  57.     }
  58.     n = split(thisUp, spl, ":")
  59.     if (n == 1) {
  60.         hours = 0
  61.     minutes = thisUp
  62.     } else {
  63.     hours = spl[1]
  64.     minutes = spl[2]
  65.     }
  66.     upTime = ((24 * days) + hours) * 60 + minutes
  67.     if (upTime > longestUptime) {
  68.         longestUptime = upTime
  69.     }
  70.     totalUptime += upTime
  71. #    print "days = " days " hours = " hours " minutes = " minutes " total = " totalUptime " upTime = " upTime
  72. }
  73.  
  74.  
  75. /^ READ *[0-9]/ {
  76.     blocksRead += $2; dirtyHits += $4; cleanHits += $6
  77. }
  78.  
  79. /^ WRITE *[0-9]/ {
  80.     blocksWritten += $2
  81. }
  82.  
  83. /^ WRITETHRU [0-9]/ {
  84.     writeThrus[WT_TOTAL] += $2
  85.     writeThrus[WT_DATA] += $4
  86.     writeThrus[WT_INDEX] += $7
  87.     writeThrus[WT_DESC] += $10
  88.     writeThrus[WT_DIR] += $13
  89.     writeThrus[WT_VM] += $16
  90. }
  91.  
  92. /^ Read/ {
  93.     cacheReads[TOTAL] += $2
  94.     remoteReads += $3
  95.     diskReads[TOTAL] += $5
  96.     rawReads += $7
  97. }
  98.  
  99. /^ Write/ {
  100.     cacheWrites[TOTAL] += $2
  101.     remoteWrites += $3
  102.     diskWrites[TOTAL] += $5
  103.     rawWrites += $7
  104. }
  105.  
  106. # The count of calls has the following format (e.g.):
  107. # "Count of calls: open(R) N   (W) N   (R/W) N   set attributes 12"
  108. /^Count of calls:/ {
  109.     callCounts[0] += $5; callCounts[1] += $7;
  110.     callCounts[2] += $9; callCounts[3] += $12
  111. }
  112.  
  113. /^File type.*Cache/ { state = 1}
  114. /^File type.*Deleted/ {state = 2}
  115. /^Deletion histogram/ {state = 3}
  116.  
  117. # Each of the data lines that we care about is preceded by one of the
  118. # type strings.  (Unfortunately, I don't think we can make that a
  119. # variable unless we make this script go through cpp or something.)
  120. # Given a particular string, check the state and add to the
  121. # appropriate field.  The I/O and overall deletion counts are just
  122. # regular arrays.  The histogram is kept in separate arrays for each
  123. # file type, indexed by row number (corresponding to time bucket).
  124. # Awk doesn't allow 2-dimensional arrays. 
  125.  
  126. /^ *temp/ {
  127.     if (state == 0) {
  128.         print("Error");
  129.     } else if (state == 1) {
  130.         cacheReads[TEMP] += $2
  131.         cacheWrites[TEMP] += $4
  132.         diskReads[TEMP] += $6
  133.         diskWrites[TEMP] += $8
  134.     } else if (state == 2) {
  135.         deletions[TEMP] += $2
  136.     } else {
  137.         row++
  138.         tempDels[row] += $NF
  139.     }
  140. }
  141. /^ *swap/ {
  142.     if (state == 0) {
  143.         print("Error");
  144.     } else if (state == 1) {
  145.         cacheReads[SWAP] += $2
  146.         cacheWrites[SWAP] += $4
  147.         diskReads[SWAP] += $6
  148.         diskWrites[SWAP] += $8
  149.     } else if (state == 2) {
  150.         deletions[SWAP] += $2
  151.     } else {
  152.         swapDels[row] += $NF
  153.     }
  154. }
  155.  
  156. /^ *obj/ {
  157.     if (state == 0) {
  158.         print("Error");
  159.     } else if (state == 1) {
  160.         cacheReads[OBJ] += $2
  161.         cacheWrites[OBJ] += $4
  162.         diskReads[OBJ] += $6
  163.         diskWrites[OBJ] += $8
  164.     } else if (state == 2) {
  165.         deletions[OBJ] += $2
  166.     } else {
  167.         objDels[row] += $NF
  168.     }
  169. }
  170. /^ *bin/ {
  171.     if (state == 0) {
  172.         print("Error");
  173.     } else if (state == 1) {
  174.         cacheReads[BINARY] += $2
  175.         cacheWrites[BINARY] += $4
  176.         diskReads[BINARY] += $6
  177.         diskWrites[BINARY] += $8
  178.     } else if (state == 2) {
  179.         deletions[BINARY] += $2
  180.     } else {
  181.         binDels[row] += $NF
  182.     }
  183. }
  184. /^ *other/ {
  185.     if (state == 0) {
  186.         print("Error");
  187.     } else if (state == 1) {
  188.         cacheReads[OTHER] += $2
  189.         cacheWrites[OTHER] += $4
  190.         diskReads[OTHER] += $6
  191.         diskWrites[OTHER] += $8
  192.     } else if (state == 2) {
  193.         deletions[OTHER] += $2
  194.     } else {
  195.         otherDels[row] += $NF
  196.         totalDels[row] += tempDels[row] + swapDels[row] + \
  197.         objDels[row] + binDels[row] + otherDels[row]
  198.     }
  199. }
  200. /^Total/ {
  201.     if (state == 2) {
  202.         deletions[TOTAL] += $2
  203.     }
  204. }
  205.  
  206. # Processing done after all counts have been finished.  First,
  207. # catch the last value of row before exiting.  Output total uptime.
  208. # Calculate the total number of I/O's and come up with the ratios.
  209. END {
  210.     if (row > maxRow) maxRow = row
  211.  
  212.     days = totalUptime / (24 * 60)
  213.     minutes = totalUptime % (24 * 60)
  214.     hours = minutes / 60
  215.     minutes = minutes % 60
  216. #    print "days = " days " hours = " hours " minutes = " minutes " total = " totaUptime " upTime = " upTime
  217. #    printf ("%d %d %d\n", days, hours, minutes)
  218.     if (days >= 1) {
  219.         dayString = sprintf("%d+", days)
  220.     } else {
  221.         dayString = ""
  222.     }
  223.     if (minutes < 10) {
  224.     minutesString = sprintf("0%d", minutes)
  225.     } else {
  226.         minutesString = minutes
  227.     }
  228.     printf("Total combined uptime for %d host(s) over %d files:  %s%d:%s\n", \
  229.        numHosts, numFiles, dayString, hours, minutesString)
  230.  
  231.     days = longestUptime / (24 * 60)
  232.     minutes = longestUptime % (24 * 60)
  233.     hours = minutes / 60
  234.     minutes = minutes % 60
  235.     if (days >= 1) {
  236.         dayString = sprintf("%d+", days)
  237.     } else {
  238.         dayString = ""
  239.     }
  240.     if (minutes < 10) {
  241.     minutesString = sprintf("0%d", minutes)
  242.     } else {
  243.         minutesString = minutes
  244.     }
  245.     printf("Longest single uptime:  %s%d:%s\n", dayString, hours, minutesString)
  246.  
  247. # Output the interesting cumulative statistics.  First, the block cache info.
  248.  
  249.     print "Block Cache Statistics (in blocks):"
  250.     printf(" READ    %10.0f   dr_hits %10.0f   cl_hits  %10.0f   hit ratio %3d\n", \
  251.          blocksRead, dirtyHits, cleanHits, \
  252.          100 * (dirtyHits + cleanHits) / blocksRead)
  253.     if (blocksWritten > 0) {
  254.          ratio = writeThrus[WT_TOTAL] / blocksWritten * 100
  255.     } else {
  256.          ratio = 0
  257.     }
  258.     printf(" WRITE   %10.0f   writethrus %10.0f                       tfc ratio %3d\n", \
  259.             blocksWritten, writeThrus[WT_TOTAL], ratio)
  260.  
  261.     print "\nByte transfers:\n"
  262.     print "Bytes:          cache          remote               disk           raw disk"
  263.  
  264.     cacheBytes = cacheReads[TOTAL];
  265.     ratio = remoteReads / cacheBytes * 100.;
  266.     printf(" Read   %13.0f   %13.0f %3d%%", cacheBytes, remoteReads, ratio)
  267.  
  268.     thruBytes = diskReads[TOTAL];
  269.     ratio = thruBytes / cacheBytes * 100.;
  270.     printf(" %13.0f %3d%%", thruBytes, ratio);
  271.  
  272.     ratio = rawReads / cacheBytes * 100.;
  273.     printf(" %13.0f %3d%%\n", rawReads, ratio);
  274.     cacheBytes = cacheWrites[TOTAL];
  275.     ratio = remoteWrites / cacheBytes * 100.;
  276.     printf(" Write  %13.0f   %13.0f %3d%%", cacheBytes, remoteWrites, ratio)
  277.  
  278.     thruBytes = diskWrites[TOTAL];
  279.     ratio = thruBytes / cacheBytes * 100.;
  280.     printf(" %13.0f %3d%%", thruBytes, ratio);
  281.  
  282.     ratio = rawWrites / cacheBytes * 100.;
  283.     printf(" %13.0f %3d%%\n", rawWrites, ratio);
  284.  
  285.     print "\nread/write ratios:"
  286.     if (cacheWrites[TOTAL] > 0) {
  287.     allCacheRatio = cacheReads[TOTAL] / cacheWrites[TOTAL];
  288.     } else {
  289.     allCacheRatio = 0
  290.     }
  291.     if (diskWrites[TOTAL] > 0) {
  292.     allDiskRatio = diskReads[TOTAL] / diskWrites[TOTAL];
  293.     } else {
  294.     allDiskRatio = 0
  295.     }
  296.     if (rawWrites > 0) {
  297.     rawRatio = rawReads / rawWrites;
  298.     } else {
  299.     rawRatio = 0
  300.     }
  301.     if (rawWrites + diskWrites[TOTAL] > 0) {
  302.     combRatio = (rawReads + diskReads[TOTAL]) / \
  303.             (rawWrites + diskWrites[TOTAL]);
  304.     } else {
  305.     combRatio = 0
  306.     }
  307.     printf ("Cache: %5.2f\tDisk: %5.2f\tRaw disk: %5.2f\t  All disk: %5.2f\n\n", \
  308.         allCacheRatio, allDiskRatio, rawRatio, combRatio)
  309.  
  310. #
  311. # Call counts
  312.     print "Count of calls:"
  313.     printf("\topen for reading: %15d\n", callCounts[0]);
  314.     printf("\t  \"      writing: %15d\n", callCounts[1]);
  315.     printf("\t  \"   read/write: %15d\n", callCounts[2]);
  316.     printf("\t  set attributes: %15d\n", callCounts[3]);
  317.     print ""
  318.  
  319. #
  320. # Per-type file I/O
  321. #
  322.  
  323. # Recalculate totals to make sure the percentages add up correctly.
  324.  
  325.     cacheReads[TOTAL] = cacheReads[TEMP] + cacheReads[SWAP] + \
  326.         cacheReads[OBJ] + cacheReads[BINARY] + cacheReads[OTHER]
  327.     cacheWrites[TOTAL] = cacheWrites[TEMP] + cacheWrites[SWAP] + \
  328.         cacheWrites[OBJ] + cacheWrites[BINARY] + cacheWrites[OTHER]
  329.     diskReads[TOTAL] = diskReads[TEMP] + diskReads[SWAP] + \
  330.         diskReads[OBJ] + diskReads[BINARY] + diskReads[OTHER]
  331.     diskWrites[TOTAL] = diskWrites[TEMP] + diskWrites[SWAP] + \
  332.         diskWrites[OBJ] + diskWrites[BINARY] + diskWrites[OTHER]
  333.  
  334.     if (cacheReads[TOTAL] > 0) {
  335.     cacheReadRatio[TEMP] = cacheReads[TEMP] / cacheReads[TOTAL]
  336.     cacheReadRatio[SWAP] = cacheReads[SWAP] / cacheReads[TOTAL]
  337.     cacheReadRatio[OBJ] = cacheReads[OBJ] / cacheReads[TOTAL]
  338.     cacheReadRatio[BINARY] = cacheReads[BINARY] / cacheReads[TOTAL]
  339.     cacheReadRatio[OTHER] = cacheReads[OTHER] / cacheReads[TOTAL]
  340.      } else {
  341.     cacheReadRatio[TEMP] = 0
  342.     cacheReadRatio[SWAP] = 0
  343.     cacheReadRatio[OBJ] = 0
  344.     cacheReadRatio[BINARY] = 0
  345.     cacheReadRatio[OTHER] = 0
  346.     }
  347.     if (cacheWrites[TOTAL] > 0) {
  348.     cacheWriteRatio[TEMP] = cacheWrites[TEMP] / cacheWrites[TOTAL]
  349.     cacheWriteRatio[SWAP] = cacheWrites[SWAP] / cacheWrites[TOTAL]
  350.     cacheWriteRatio[OBJ] = cacheWrites[OBJ] / cacheWrites[TOTAL]
  351.     cacheWriteRatio[BINARY] = cacheWrites[BINARY] / cacheWrites[TOTAL]
  352.     cacheWriteRatio[OTHER] = cacheWrites[OTHER] / cacheWrites[TOTAL]
  353.      } else {
  354.     cacheWriteRatio[TEMP] = 0
  355.     cacheWriteRatio[SWAP] = 0
  356.     cacheWriteRatio[OBJ] = 0
  357.     cacheWriteRatio[BINARY] = 0
  358.     cacheWriteRatio[OTHER] = 0
  359.     }
  360.     if (diskReads[TOTAL] > 0) {
  361.     diskReadRatio[TEMP] = diskReads[TEMP] / diskReads[TOTAL]
  362.     diskReadRatio[SWAP] = diskReads[SWAP] / diskReads[TOTAL]
  363.     diskReadRatio[OBJ] = diskReads[OBJ] / diskReads[TOTAL]
  364.     diskReadRatio[BINARY] = diskReads[BINARY] / diskReads[TOTAL]
  365.     diskReadRatio[OTHER] = diskReads[OTHER] / diskReads[TOTAL]
  366.      } else {
  367.     diskReadRatio[TEMP] = 0
  368.     diskReadRatio[SWAP] = 0
  369.     diskReadRatio[OBJ] = 0
  370.     diskReadRatio[BINARY] = 0
  371.     diskReadRatio[OTHER] = 0
  372.     }
  373.     if (diskWrites[TOTAL] > 0) {
  374.     diskWriteRatio[TEMP] = diskWrites[TEMP] / diskWrites[TOTAL]
  375.     diskWriteRatio[SWAP] = diskWrites[SWAP] / diskWrites[TOTAL]
  376.     diskWriteRatio[OBJ] = diskWrites[OBJ] / diskWrites[TOTAL]
  377.     diskWriteRatio[BINARY] = diskWrites[BINARY] / diskWrites[TOTAL]
  378.     diskWriteRatio[OTHER] = diskWrites[OTHER] / diskWrites[TOTAL]
  379.      } else {
  380.     diskWriteRatio[TEMP] = 0
  381.     diskWriteRatio[SWAP] = 0
  382.     diskWriteRatio[OBJ] = 0
  383.     diskWriteRatio[BINARY] = 0
  384.     diskWriteRatio[OTHER] = 0
  385.     }
  386.  
  387.     print "Per-type file I/O, in bytes:"
  388.     print "\nFile type    Cache(R)          Cache(W)           Disk(R)           Disk(W)"
  389.    
  390.     for (i = TEMP; i < TOTAL; i++) {
  391.         printf("%-5s ", strings[i]);
  392.         printf(" %12.0f %3d%%", cacheReads[i], cacheReadRatio[i] * 100  + .5)
  393.         printf(" %12.0f %3d%%", cacheWrites[i], cacheWriteRatio[i] * 100  + .5)
  394.         printf(" %12.0f %3d%%", diskReads[i], diskReadRatio[i] * 100  + .5)
  395.         printf(" %12.0f %3d%%\n", diskWrites[i], diskWriteRatio[i] * 100  + .5)
  396.     }
  397.  
  398. # Output the total per-type deletion counts and the R/W ratios
  399.     if (deletions[TOTAL] > 0) {
  400.         hdr = "        Bytes Deleted"
  401.         tail = sprintf(" %15.0f 100%%", deletions[TOTAL]);
  402.     } else {
  403.         hdr = ""; tail = ""
  404.     }
  405.     printf("\nFile type   Cache R/W    Disk R/W    Read Hits   Write Tfc%s", hdr);
  406.     for (i = 0; i < TOTAL; i++) {
  407.     if (cacheWrites[i] > 0) {
  408.         cacheRatio = cacheReads[i] / cacheWrites[i];
  409.         trafficRatio = diskWrites[i] / cacheWrites[i];
  410.     } else {
  411.         cacheRatio = 0
  412.         trafficRatio = 0
  413.     }
  414.     if (cacheReads[i] > 0) {
  415.         readHitRatio = 1 - diskReads[i] / cacheReads[i];
  416.     } else {
  417.         readHitRatio = 0
  418.     }
  419.     if (diskWrites[i] > 0) {
  420.         diskRatio = diskReads[i] / diskWrites[i];
  421.     } else {
  422.         diskRatio = 0
  423.     }
  424.         if (deletions[TOTAL] > 0) {
  425.         delStr = sprintf(" %15.0f %3d%%", deletions [i], \
  426.             deletions [i] / deletions[TOTAL] * 100 + 0.5)
  427.     } else {
  428.         delStr = ""
  429.     }
  430.     printf("\n%-5s          %6.2f      %6.2f       %6.2f      %6.2f%s", \
  431.            strings[i], cacheRatio, diskRatio, readHitRatio, \
  432.            trafficRatio, delStr);
  433.     }
  434.     if (cacheReads[TOTAL] > 0) {
  435.     readHitRatio = 1 - diskReads[TOTAL] / cacheReads[TOTAL];
  436.     } else {
  437.     readHitRatio = 0
  438.     }
  439.     if (cacheWrites[TOTAL] > 0) {
  440.     trafficRatio = diskWrites[TOTAL] / cacheWrites[TOTAL];
  441.     } else {
  442.     trafficRatio = 0
  443.     }
  444.     printf("\nTotal          %6.2f      %6.2f       %6.2f      %6.2f%s\n", \
  445.         allCacheRatio, allDiskRatio, readHitRatio, trafficRatio, tail);
  446.     if (totalDels[maxRow] > 0) {
  447.         timeStrings[0] = "1 sec "
  448.         timeStrings[1] = "2 secs"
  449.     timeStrings[2] = "3 secs"
  450.     timeStrings[3] = "4 secs"
  451.     timeStrings[4] = "5 secs"
  452.     timeStrings[5] = "6 secs"
  453.     timeStrings[6] = "7 secs"
  454.     timeStrings[7] = "8 secs"
  455.     timeStrings[8] = "9 secs"
  456.     timeStrings[9] = "10 secs"
  457.     timeStrings[10] = "20 secs"
  458.     timeStrings[11] = "30 secs"
  459.     timeStrings[12] = "40 secs"
  460.     timeStrings[13] = "50 secs"
  461.     timeStrings[14] = "1 min "
  462.     timeStrings[15] = "2 mins"
  463.     timeStrings[16] = "3 mins"
  464.     timeStrings[17] = "4 mins"
  465.     timeStrings[18] = "5 mins"
  466.     timeStrings[19] = "6 mins"
  467.     timeStrings[20] = "7 mins"
  468.     timeStrings[21] = "8 mins"
  469.     timeStrings[22] = "9 mins"
  470.     timeStrings[23] = "10 mins"
  471.     timeStrings[24] = "20 mins"
  472.     timeStrings[25] = "30 mins"
  473.     timeStrings[26] = "40 mins"
  474.     timeStrings[27] = "50 mins"
  475.     timeStrings[28] = "1 hr "
  476.     timeStrings[29] = "2 hrs"
  477.     timeStrings[30] = "3 hrs"
  478.     timeStrings[31] = "4 hrs"
  479.     timeStrings[32] = "5 hrs"
  480.     timeStrings[33] = "6 hrs"
  481.     timeStrings[34] = "7 hrs"
  482.     timeStrings[35] = "8 hrs"
  483.     timeStrings[36] = "9 hrs"
  484.     timeStrings[37] = "10 hrs"
  485.     timeStrings[38] = "15 hrs"
  486.     timeStrings[39] = "20 hrs"
  487.     timeStrings[40] = "1 day "
  488.     timeStrings[41] = "2 days"
  489.     timeStrings[42] = "3 days"
  490.     timeStrings[43] = "4 days"
  491.     timeStrings[44] = "5 days"
  492.     timeStrings[45] = "6 days"
  493.     timeStrings[46] = "7 days"
  494.     timeStrings[47] = "8 days"
  495.     timeStrings[48] = "9 days"
  496.     timeStrings[49] = "10 days"
  497.     timeStrings[50] = "20 days"
  498.     timeStrings[51] = "30 days"
  499.     timeStrings[52] = "40 days"
  500.     timeStrings[53] = "50 days"
  501.     timeStrings[54] = "60 days"
  502.     timeStrings[55] = "90 days"
  503.     timeStrings[56] = "120 days"
  504.     timeStrings[57] = "180 days"
  505.     timeStrings[58] = "240 days"
  506.     timeStrings[59] = "300 days"
  507.     timeStrings[60] = "360 days"
  508.     timeStrings[61] = ">360 days"
  509.         numTimesToPrint = maxRow
  510.  
  511.     printf(" \nPercentiles for bytes deleted, by type.  Total is in 1K blocks:\n\n");
  512.     printf("      Time   %6s %6s %6s %6s %6s   Cumulative         Cum. Total\n", \
  513.              strings[0],  strings[1], strings[2], strings[3], strings[4])
  514.     for (row = 0; row <= maxRow; row++) {
  515.         printf("%10s    ", timeStrings[row]);
  516.             if (tempDels[maxRow] > 0) {
  517.              ratio = tempDels[row] / tempDels[maxRow];
  518.         } else {
  519.              ratio = 0;
  520.         }
  521.         printf("%5.0f  ", ratio * 100);
  522.             if (swapDels[maxRow] > 0) {
  523.              ratio = swapDels[row] / swapDels[maxRow];
  524.         } else {
  525.              ratio = 0;
  526.         }
  527.         printf("%5.0f  ", ratio * 100);
  528.             if (objDels[maxRow] > 0) {
  529.              ratio = objDels[row] / objDels[maxRow];
  530.         } else {
  531.              ratio = 0;
  532.         }
  533.         printf("%5.0f  ", ratio * 100);
  534.             if (binDels[maxRow] > 0) {
  535.              ratio = binDels[row] / binDels[maxRow];
  536.         } else {
  537.              ratio = 0;
  538.         }
  539.         printf("%5.0f  ", ratio * 100);
  540.             if (otherDels[maxRow] > 0) {
  541.              ratio = otherDels[row] / otherDels[maxRow];
  542.         } else {
  543.              ratio = 0;
  544.         }
  545.         printf("%5.0f  ", ratio * 100);
  546.         printf("      %5.0f    %15.0f\n", \
  547.                  totalDels[row] / totalDels[maxRow] * 100, totalDels[row]);
  548.  
  549.     }
  550.     }
  551.     print ""
  552. }
  553.